/** Implementation of MIPS Assembler Class.
 * @file 
 * @author Jeremy Schultz
 */
#include "AssemblerMIPS.h"

using namespace std;

//-----------------------------------------------------------------------------
// Constructor
AssemblerMIPS::AssemblerMIPS(istream &_in, ostream &_out)  {
	in = &_in;
	out = &_out;
}


//-----------------------------------------------------------------------------
// Unique ID
string AssemblerMIPS::uniqueLabel(string label) {
	static int uniqueID = 0;

	stringstream ss;
	ss << label << uniqueID++;

	return ss.str();
}

//-----------------------------------------------------------------------------
// First Pass, build a var label table
//  Do not need a address label table, since MIPS can use labels
void AssemblerMIPS::firstPass() {
	string op;
	int arg1, arg2;

	for( (*in) >> op; in->good() == true; (*in) >> op) {
		if (op == "DEFARG") {
			(*in) >> arg1 >> arg2;
			// each variable is 4 bytes
			varSize[arg1] = arg2 * 4;

		}else if (op == "ENDPROG") {
			break;

		// Skip one arg 
		}else if (op == "ARROW" || op == "ASSIGN" || op == "BAR" || 
				  op == "CONSTANT" || op == "FI" || op == "READ" || 
				  op == "WRITE" || op == "DEFADDR") {
			(*in) >> arg1;

		// Skip two args 
		}else if (op == "CALL" || op == "INDEX" || op == "PROC" || 
				  op == "PROG" || op == "VARIABLE") {
			(*in) >> arg1 >> arg2;
		}
	}
}

//-----------------------------------------------------------------------------
// Second Pass: output the MIPS code 
// $sp: stack pointer (first free location on the stack)
// $fp: frame pointer (base)
// $ra: return address
// $s0: dynamic link
void AssemblerMIPS::secondPass() {
	string op;
	int arg1, arg2;

	// Header
	(*out)	<< "## Generated MIPS from pl source" << endl 
			<< "## " << endl
			<< "  .text                     " << endl
			<< endl;

	for( (*in) >> op; in->good() == true; (*in) >> op) {

		if (op == "ADD")	{
			(*out)	
				<< "## ADD " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  add     $t2, $t0, $t1 " << 	"\t# answer = num1 + num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;

		}else if (op == "AND")	{
			(*out)	
				<< "## AND " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  and     $t2, $t0, $t1 " << 	"\t# answer = num1 && num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;
			
		}else if (op == "ARROW")	{
			(*in) >> arg1;

			(*out)	
				<< "## ARROW <jump label>" << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = x " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t0, 0($sp)   " << 	"\t# x = stack[top of stack]" << endl
				<< "  beqz    $t0, label"<<arg1<<   "\t# x == 0 goto label<jump label>" << endl
				<< endl;

		}else if (op == "ASSIGN")	{
			(*in) >> arg1;
			arg1 = arg1 * 4;	// each variable is 4 bytes
			string sWhile = uniqueLabel("while");
			string eWhile = uniqueLabel("endWhile");

			(*out)	
				<< "## ASSIGN <# of assigns> " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = x " << endl
				<< "##   $t1 = lastAssign, Used in loop " << endl
				<< "##   $t2 = value" << endl
				<< "##   $t3 = varAddress " << endl
				<< "  addiu   $t1, $sp, "<<arg1<<	"\t\t# sp = sp + <# of assigns>" << endl
				<< "  addiu   $sp, $sp, "<<arg1*2<<	"\t\t# sp = sp + (2*<# of assigns>)" << endl
				<< "  move    $t0, $sp      " <<	"\t# x = sp" << endl
				//while loop 
				<< sWhile << ":" <<						endl
				<< "  ble     $t0, $t1 "<<eWhile<<	"\t# Exit loop if (x <= lastAssign) " << endl

				<< "  subu    $t3, $t0, "<<arg1<<	"\t\t# varAddress = x + <# of assigns>" << endl
				<< "  lw	  $t2, 0($t3)   " <<	"\t# value = stack[varAddress]" << endl

				<< "  lw	  $t3, 0($t0)   " <<	"\t# varAddress = stack[varAddress]" << endl
				<< "  sw	  $t2, 0($t3)   " <<	"\t# stack[varAddress] = value" << endl

				<< "  subu    $t0, $t0, 4   " <<	"\t# x = x - (memory size)" << endl
				<< "  b       "<<sWhile<<"  " <<	"\t\t# Goto loop start " << endl
				// end loop
				<< eWhile << ":" << endl
				<< endl;

		}else if (op == "BAR")	{
			(*in) >> arg1;

			(*out)	
				<< "## BAR <jump label>" << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = x " << endl
				<< "  b       label"<<arg1<<	    "\t\t# Goto label<jump label> " << endl
				<< endl;

		}else if (op == "CALL")		{
			(*in) >> arg1 >> arg2;

			string sWhile = uniqueLabel("while");
			string eWhile = uniqueLabel("endWhile");

			(*out)	
				<< "## CALL <level> <label> " <<	endl
				<< "## Registers Used: " <<			endl
				<< "##   $t0 = x " <<				endl
				<< "##   $t1 = level " <<			endl
				<< "  subu    $sp, $sp, 32   " <<	"\t# Allocate stack frame of 32" << endl
				<< "  li      $t1, "<<arg1<<		"\t\t# level = <level> " << endl
				<< "  move    $t0, $fp      " <<	"\t# x = fp" << endl
				// while start 
				<< sWhile << ":" <<						endl
				<< "  blez    $t1, "<<eWhile  <<	"\t# (level <= 0) goto end While " << endl
				<< "  lw      $t0, 0($t0)   " <<	"\t# x = stack[x]" << endl
				<< "  subu    $t1, $t1, 1   " <<	"\t# level = level - 1" << endl
				<< "  b       "<<sWhile<<"  " <<	"\t\t# Goto while start " << endl
				// end while
				<< eWhile << ":" <<					endl
				<< "  sw      $t0, 32($sp)   " <<	"\t# stack_frame[0] = x " << endl
				<< "  sw      $fp, 28($sp)   " <<	"\t# stack_frame[1] = fp " << endl
				<< "  sw      $ra, 24($sp)   " <<	"\t# stack_frame[2] = ra " << endl
				<< "  addiu   $fp, $sp, 32   " <<	"\t# fp = sp + 32" << endl

				<< "  jal     label"<<arg2<<		"\t\t# Goto label<label> " << endl
				//<< "  sw      $ra, -8($fp)   " <<	"\t# ra = fp -8 (stack_frame[8]) " << endl
				<< endl;

		}else if (op == "CONSTANT")		{
			(*in) >> arg1;
			(*out)	
				<< "## CONSTANT <value> " << endl
				<< "## Registers Used:  " << endl
				<< "##   $t0 = x        " << endl
				<< "  subu    $sp, $sp, 4   " <<	"\t# Allocate " << endl
				<< "  li      $t0, "<<arg1<<        "\t\t# x = <value>" << endl
				<< "  sw      $t0, 4($sp)   " <<	"\t# stack[$sp - 4] = x " << endl
				<< endl;

		}else if (op == "DIVIDE")	{
			(*out)	
				<< "## DIVIDE " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  div     $t2, $t0, $t1 " << 	"\t# answer = num1 / num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;

		}else if (op == "ENDPROC")	{
			(*out)	
				<< "## ENDPROC " << endl
				<< "  move    $sp, $fp      " << 	"\t# sp = fp " << endl
				<< "  move    $t0, $ra      " << 	"\t# tempReturn = ra " << endl
				<< "  lw      $ra, -8($fp)  " << 	"\t# fp = stack[fp - 4]" << endl
				<< "  lw      $fp, -4($fp)  " << 	"\t# fp = stack[fp - 4]" << endl
				//<< "  jr      $ra           " <<    "\t# return to tempReturn" <<endl
				<< "  jr      $t0           " <<    "\t# return to tempReturn" <<endl
				<< endl;

		}else if (op == "ENDPROG")	{
			(*out)	
				<< "## ENDPROG" << endl
				<< "  li      $v0, 10       " <<	"\t# Code 10 is exit" << endl
				<< "  syscall               " <<	"\t# Exit Program" << endl
				<< endl
				// Data area 
				<< "## Data Area:" << endl 
				<< "  .data                 " << endl
				<< "output:   .asciiz \"Output: \" " << endl
				<< "input:    .asciiz \"Input: \" " << endl
				<< "eRange:   .asciiz \"MIPS Error :: Invalid Array Range :: Line \" " << endl
				<< "eIf:      .asciiz \"MIPS Error :: If statement failed :: Line \" " << endl
				<< "newline:  .asciiz \"\\n\"      " << endl
				<< endl;

		}else if (op == "EQUAL")	{
			(*out)	
				<< "## EQUAL " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  seq     $t2, $t0, $t1 " << 	"\t# answer = num1 \% num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;

		}else if (op == "FI")	{
			(*in) >> arg1;

			(*out)	
				<< "## FI <line number>" << endl
				<< "  la      $a0, eIf      " <<	"\t# Load Error If string to be printed" << endl
				<< "  li      $v0, 4        " <<	"\t# Load print_string syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				<< "  li      $a0, "<<arg1<<		"\t# Load <line number> to be printed" << endl
				<< "  li      $v0, 1        " <<	"\t# Load print_int syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				<< "  la      $a0, newline  " <<	"\t# Load newline to be printed" << endl
				<< "  li      $v0, 4        " <<	"\t# Load print_string syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				<< endl;


		}else if (op == "GREATER")	{
			(*out)	
				<< "## GREATER " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  sgt     $t2, $t0, $t1 " << 	"\t# answer = num1 > num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;

		}else if (op == "INDEX")	{
			(*in) >> arg1 >> arg2;

			string bError = uniqueLabel("boundError");
			string end = uniqueLabel("endIndex");

			(*out)	
				<< "## INDEX <upper bound> <line number> " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = x " << endl
				<< "##   $t1 = address " << endl
				<< "  lw      $t0, 4($sp)   " <<	"\t# x = stack[top of stack]" << endl
				<< "  addiu   $sp, $sp, 4   " <<	"\t# sp = sp + 4" << endl

				// IF
				<< "  blt     $t0, 1, "<<bError<<	"\t# x < 1 goto boundError" << endl
				<< "  bgt     $t0, "<<arg1<<","<<bError<<"\t# x > <upper bound> goto boundError" << endl

				// No Bound Error
				<< "  subu    $t0, $t0, 1   " <<	"\t# x = x - 1" << endl
				<< "  mul     $t0, $t0, 4   " <<	"\t# x = x * 4" << endl
				<< "  lw      $t1, 4($sp)   " <<	"\t# address = stack[top of stack]" << endl
				<< "  subu    $t1, $t1, $t0 " <<	"\t# address = address - x" << endl
				<< "  sw      $t1, 4($sp)   " <<	"\t# stack[top of stack] = address" << endl
				<< "  b       "<<end<<"     " <<	"\t\t# Goto End of Index" << endl

				// Bound Error 
				<< bError << ":" <<	endl
				<< "  la      $a0, eRange   " <<	"\t# Load Error Range string to be printed" << endl
				<< "  li      $v0, 4        " <<	"\t# Load print_string syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				<< "  li      $a0, "<<arg2<<		"\t# Load <line number> to be printed" << endl
				<< "  li      $v0, 1        " <<	"\t# Load print_int syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				<< "  la      $a0, newline  " <<	"\t# Load newline to be printed" << endl
				<< "  li      $v0, 4        " <<	"\t# Load print_string syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				// End index 
				<< end << ":" <<	endl
				<< endl;

		}else if (op == "LESS")		{
			(*out)	
				<< "## LESS " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  slt     $t2, $t0, $t1 " << 	"\t# answer = num1 < num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;

		}else if (op == "MINUS")	{
			(*out)	
				<< "## MINUS " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  neg     $t0, $t0      " << 	"\t# num1 = -num1" << endl
				<< "  sw      $t0, 4($sp)   " << 	"\t# stack[top of stack] = num1" << endl
				<< endl;

		}else if (op == "MODULO")	{
			(*out)	
				<< "## MODULO " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  rem     $t2, $t0, $t1 " << 	"\t# answer = num1 \% num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;

		}else if (op == "MULTIPLY")		{
			(*out)	
				<< "## MULTIPLY " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  mul     $t2, $t0, $t1 " << 	"\t# answer = num1 * num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;
			
		}else if (op == "NOT")	{
			(*out)	
				<< "## NOT " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				// There was issues with MIPS not, it would not signed numbers
				//<< "  not     $t0, $t0      " << 	"\t# num1 = -num1" << endl
				<< "  seq     $t0, $t0, $0  " << 	"\t# !num1 (num1==0;1==0:False,0==0:True)" << endl
				<< "  sw      $t0, 4($sp)   " << 	"\t# stack[top of stack] = num1" << endl
				<< endl;

		}else if (op == "OR")	{
			(*out)	
				<< "## OR " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  or      $t2, $t0, $t1 " << 	"\t# answer = num1 || num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;
			

		}else if (op == "PROC")		{
			(*in) >> arg1 >> arg2;
			arg1 = varSize[arg1];

			(*out)	
				<< "## PROC <variable length> <label> " << endl
				<< "  subu    $sp, $sp, "<<arg1<<	"\t\t# Allocate local vars" << endl
				<< "  b       label"<<arg2<<	    "\t\t# Goto label<label> " << endl
				<< endl;
			
		}else if (op == "PROG")		{
			(*in) >> arg1 >> arg2;
			arg1 = varSize[arg1];
			(*out)
				<< "## PROG varLenth(label) address(label) " << endl
				<< "## Registers Used: " << endl
				<< "##   $sp = stack pointer (first free location on the stack) " << endl
				<< "##   $fp = frame pointer (AKA base) " << endl
				<< "##   $ra = return address" << endl
				<< "##  " << endl
				<< "main:                   " << endl
				<< "  move    $fp, $sp      " <<	"\t# fp = sp" << endl
				//<< "  move    $t0, $fp      " <<	"\t# x = fp" << endl
				<< "  subu    $sp, $sp, 32  " <<	"\t# Allocate stack frame " << endl
				<< "  sw      $fp, 32($sp)   " <<	"\t# stack_frame[0] = x " << endl
				<< "  sw      $fp, 28($sp)   " <<	"\t# stack_frame[1] = fp " << endl
				//<< "  sw      $ra, 24($sp)   " <<	"\t# stack_frame[2] = ra " << endl

				<< "  subu    $sp, $sp, "<<arg1<<	"\t\t# Allocate local vars" << endl

				<< "  b       label"<<arg2<<	    "\t\t# Goto label<label> " << endl
				<< endl;

		}else if (op == "READ")		{
			string sWhile = uniqueLabel("while");
			string eWhile = uniqueLabel("endWhile");

			(*in) >> arg1;
			arg1 = arg1 * 4;	// each variable is 4 bytes

			(*out)	
				<< "## READ <# of reads> " << endl
				<< "## Registers Used: " << endl
				<< "##   $t0 = x " << endl
				<< "##   $t1 = lastRead, Used in loop " << endl
				<< "##   $t2 = varAddress " << endl
				<< "  move    $t1, $sp      " <<	"\t# lastRead = sp" << endl
				<< "  addiu   $sp, $sp, "<<arg1<<   "\t\t# sp = sp + arg1" << endl
				<< "  move    $t0, $sp      " <<	"\t# x = sp" << endl
				//while loop 
				<< sWhile << ":" <<						endl
				<< "  ble     $t0, $t1 "<<eWhile<<	"\t# Exit loop if (x <= lastRead) " << endl

				<< "  la      $a0, input    " <<	"\t# Load 'Input: ' to be printed" << endl
				<< "  li      $v0, 4        " <<	"\t# Load print_string syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				<< "  li      $v0, 5        " <<	"\t# Load read_int syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl
				<< "  lw      $t2, 0($t0)   " <<	"\t# varAddress = stack[x]" << endl
				<< "  sw      $v0, 0($t2)   " <<	"\t# stack[varAddress] = user_input_int" << endl

				<< "  subu    $t0, $t0, 4   " <<	"\t# x = x - 4" << endl
				<< "  b       "<<sWhile<<"  " <<	"\t\t# Goto loop start " << endl
				// end loop
				<< eWhile << ":" <<					endl
				<< endl;


		}else if (op == "SUBTRACT")		{
			(*out)	
				<< "## SUBTRACT " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = num1 " << endl
				<< "##   $t1 = num2 " << endl
				<< "##   $t2 = answer " << endl
				<< "  addiu   $sp, $sp, 4   " << 	"\t# sp + 4" << endl
				<< "  lw      $t1, 0($sp)   " << 	"\t# num2 = stack[sp]" << endl
				<< "  lw      $t0, 4($sp)   " << 	"\t# num1 = stack[top of stack]" << endl
				<< "  sub     $t2, $t0, $t1 " << 	"\t# answer = num1 - num2" << endl
				<< "  sw      $t2, 4($sp)   " << 	"\t# stack[top of stack] = answer" << endl
				<< endl;

		}else if (op == "VALUE")	{
			(*out)	
				<< "## VALUE " << endl
				<< "## Registers Used: " <<	endl
				<< "##   $t0 = x " << endl
				<< "  lw    $t0, 4($sp)     " <<	"\t# x = stack[top of stack]" << endl
				<< "  lw    $t0, 0($t0)     " <<	"\t# x = stack[x]" << endl
				<< "  sw    $t0, 4($sp)     " <<	"\t# x = stack[top of stack]" << endl
				<< endl;

		}else if (op == "VARIABLE")		{
			string sWhile = uniqueLabel("while");
			string eWhile = uniqueLabel("endWhile");

			(*in) >> arg1 >> arg2;
			// In MIPS a variable is 4 bytes 
			//  Thus an offset of 1 is 4 or (<offset> * 4)
			// In PL local var is at (frame pointer + <offset>), where the first offset is 3
			// In MIPS the frame pointer has minimum of 32 bytes (stated in the manual)
			//  Thus (3*4) + 20 is the first local var
			// Finally this gives us
			//   (<offset> * 4) + 20
			arg2 = (arg2 * 4) + 20;

			(*out)	
				<< "## VARIABLE <level> <offset> " <<	endl
				<< "## Registers Used: " <<			endl
				<< "##   $t0 = x " <<				endl
				<< "##   $t1 = level " <<			endl
				<< "  subu    $sp, $sp, 4   " <<	"\t# Allocate " << endl
				<< "  li      $t1, "<<arg1<<		"\t\t# level = <level> " << endl
				<< "  move    $t0, $fp      " <<	"\t# x = fp" << endl
				//while loop 
				<< sWhile << ":" <<						endl
				<< "  blez    $t1, "<<eWhile  <<	"\t# (level <= 0) goto end While " << endl
				<< "  lw      $t0, 0($t0)   " <<	"\t# x = stack[x]" << endl
				<< "  subu    $t1, $t1, 1   " <<	"\t# level = level - 1" << endl
				<< "  b       "<<sWhile<<"  " <<	"\t\t# Goto loop start " << endl
				// end loop
				<< eWhile << ":" <<					endl
				<< "  subu    $t0, $t0, "<<arg2<<	"\t\t# x = x - <offset> " << endl
				<< "  sw      $t0, 4($sp)   " <<	"\t# stack[top of stack] = x " << endl
				<< endl;

		}else if (op == "WRITE")	{
			string sWhile = uniqueLabel("while");
			string eWhile = uniqueLabel("endWhile");

			(*in) >> arg1;
			arg1 = arg1 * 4;	// each variable is 4 bytes

			(*out)	
				<< "## WRITE <# of writes> " <<	endl
				<< "## Registers Used: " <<			endl
				<< "##   $t0 = lastWrite, Used in loop " <<			endl
				<< "##   $t1 = x " <<				endl
				<< "  move    $t0, $sp      " <<	"\t# lastWrite = sp" << endl
				<< "  addiu   $sp, $sp, "<<arg1<<   "\t\t# sp = sp + arg1" << endl
				<< "  move    $t1, $sp      " <<	"\t# x = sp" << endl
				//while loop 
				<< sWhile << ":" <<						endl
				<< "  ble     $t1, $t0 "<<eWhile<<	"\t# Exit loop if (x <= lastWrite) " << endl

				<< "  la      $a0, output   " <<	"\t# Load 'Output: ' to be printed" << endl
				<< "  li      $v0, 4        " <<	"\t# Load print_string syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				<< "  lw      $a0, 0($t1)   " <<	"\t# Load stack[x] to be printed" << endl
				<< "  li      $v0, 1        " <<	"\t# Load print_int syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				<< "  la      $a0, newline  " <<	"\t# Load newline to be printed" << endl
				<< "  li      $v0, 4        " <<	"\t# Load print_string syscall" << endl
				<< "  syscall               " <<	"\t# Execute Syscall " << endl

				<< "  subu    $t1, $t1, 4   " <<	"\t# x = x - (memory size)" << endl
				<< "  b       "<<sWhile<<"  " <<	"\t\t# Goto loop start " << endl
				// end loop
				<< eWhile << ":" <<					endl
				<< endl;

		}else if (op == "DEFADDR")	{
			(*in) >> arg1;
			(*out)	
				<< "## DEFADDR <label> " <<	endl
				<< "label" << arg1 << ":" << endl
				<< endl;

		}else if (op == "DEFARG")	{
			(*in) >> arg1 >> arg2;

		}else {
			cerr << "Unhandled op" << endl;
		}
	}
}

